package com.sichen.product.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sichen.common.constant.ProductConstant;
import com.sichen.common.utils.PageUtils;
import com.sichen.common.utils.Query;
import com.sichen.product.dao.AttrAttrgroupRelationDao;
import com.sichen.product.dao.AttrDao;
import com.sichen.product.dao.AttrGroupDao;
import com.sichen.product.dao.CategoryDao;
import com.sichen.product.entity.AttrAttrgroupRelationEntity;
import com.sichen.product.entity.AttrEntity;
import com.sichen.product.entity.AttrGroupEntity;
import com.sichen.product.entity.CategoryEntity;
import com.sichen.product.service.AttrService;
import com.sichen.product.service.CategoryService;
import com.sichen.product.vo.AttrRespVo;
import com.sichen.product.vo.AttrVo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {

    @Resource
    AttrAttrgroupRelationDao relationDao;

    @Resource
    AttrGroupDao attrGroupDao;

    @Resource
    CategoryDao categoryDao;

    @Resource
    CategoryService categoryService;

    /**
     * 根据前端传递的分页数据查询商品属性的分页集合
     * @param params 分页数据
     * @return 分页过的商品数据集合
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<>()
        );

        return new PageUtils(page);
    }

    /**
     * 新增属性
     * @param attrVo 属性的集合
     * @return 保存信息是否成功
     */
    @Override
    public void saveAttrVo(AttrVo attrVo) {
        //1.先将前端传递过来的AttrEntity的属性进行封装
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVo, attrEntity);
        //2.保存属性的基本数据
        this.save(attrEntity);
        //3.确定传递了属性分组id , 保存属性&属性分组的关联关系
        if (attrVo.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() && attrVo.getAttrGroupId() != null) {
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrGroupId(attrVo.getAttrGroupId());
//            AttrEntity entity = this.baseMapper.selectOne(new QueryWrapper<AttrEntity>().eq("attr_name", attrVo.getAttrName()));
            relationEntity.setAttrId(attrVo.getAttrId());
            relationDao.insert(relationEntity);
        }
    }

    /**
     * 获取分类销售属性|获取分类的规格属性
     * @param params 前端传递的分页属性
     * @param catelogId 分类的id
     * @param type 属性的分类 : 销售|规格
     * @return 分页过的销售|规格属性
     */
    @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type) {
        //1.判断传递过来的是什么类型 , 根据类型拼接查询条件
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>()
                .eq("attr_type", "base".equalsIgnoreCase(type) ? ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() : ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());
        //2.如果传递过来的有分类的id , 说明是按照分类进行查询的 , 查询条件
        if (catelogId != 0) {
            wrapper.eq("catelog_id", catelogId);
        }
        //3.判断前端传递的参数中是否有模糊查询的条件 , 有就添加模糊查询的条件
        String key = (String) params.get("key");
        if (!StringUtils.isBlank(key)) {
            //不为空 , 拼接模糊查询的条件
            wrapper.and((wrappers) -> wrappers.eq("attr_id", key).or().like("attr_name", key));
        }
        //4.调用分页方法 , 对数据进行分页
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), wrapper);
        PageUtils pageUtils = new PageUtils(page);
        //5.获取查询出的属性数据
        List<AttrEntity> records = page.getRecords();
        //6.对查询出的数据进行操作 , 数据展示的界面还要展示 所属分组名称 , 和所属分类名称
        List<AttrRespVo> respVos = records.stream().map(attrEntity -> {
            //6.1.AttrRespVo用来封装返回前端的数据 , 增加了一些属性
            AttrRespVo attrRespVo = new AttrRespVo();
            BeanUtils.copyProperties(attrEntity, attrRespVo);
            //6.2.判断type是否是查询规格属性 , 销售属性不需要展示分组名称
            if ("base".equalsIgnoreCase(type)) {
                //6.2.1.是查询规格属性 , 封装属性分组名称
                AttrAttrgroupRelationEntity relationEntity = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));
                //6.2.2.判断查询出的(属性&属性分组)信息不为空 , 并且属性分组id不为空 , 说名这个属性绑定的有属性分组
                if (relationEntity != null && relationEntity.getAttrGroupId() != null) {
                    AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
                    attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }
            //6.3.根据分类id查询分类属性
            CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
            if (categoryEntity != null) {
                //6.3.1.封装分类名称
                attrRespVo.setCatelogName(categoryEntity.getName());
            }
            return attrRespVo;
        }).collect(Collectors.toList());
        pageUtils.setList(respVos);
        return pageUtils;
    }

    /**
     * 查询属性详情&所属分类
     * @param attrId 属性的ID
     * @return 返回封装的属性
     */
    @Override
    public AttrRespVo getAttrInfo(Long attrId) {
        AttrRespVo attrRespVo = new AttrRespVo();
        //1.先根据属性id查询出属性详情
        AttrEntity attrEntity = this.getById(attrId);
        BeanUtils.copyProperties(attrEntity, attrRespVo);
        //2.判断是否是查询规格属性 , 设置分组信息
        if (attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
            //2.1.根据属性id , 查询属性的信息
            AttrAttrgroupRelationEntity attrgroupRelation = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId));
            if (attrgroupRelation != null) {
                //2.1.1.设置属性分组id
                attrRespVo.setAttrGroupId(attrgroupRelation.getAttrGroupId());
                //2.1.2.设置属性分组名称
                AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupRelation.getAttrGroupId());
                if (attrGroupEntity != null) {
                    attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }
        }
        //3.设置分类信息
        Long catelogId = attrEntity.getCatelogId();
        //4.获取分类的全路径信息
        Long[] catelogPath = categoryService.findCatelogPath(catelogId);
        attrRespVo.setCatelogPath(catelogPath);
        CategoryEntity categoryEntity = categoryDao.selectById(catelogId);
        if (categoryEntity != null) {
            //4.1.设置分类的名称
            attrRespVo.setCatelogName(categoryEntity.getName());
        }
        return attrRespVo;
    }


    /**
     * 修改属性参数
     * @param attrVo 前端传递的属性参数
     * @return 修改信息是否成功
     */
    @Override
    public void updateAttr(AttrVo attrVo) {
        //1.先修改自身的属性
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVo, attrEntity);
        this.updateById(attrEntity);
        //2.判断属性类型是规格属性
        if (attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
            //2.1.修改关联表中属性分组信息
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrGroupId(attrVo.getAttrGroupId());
            relationEntity.setAttrId(attrVo.getAttrId());
            //2.2.判断(属性&属性分组表)中是否有绑定的信息 , 有就是修改 , 没有就是新增绑定关系
            Integer count = relationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVo.getAttrId()));
            if (count > 0) {
                relationDao.update(relationEntity, new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVo.getAttrId()));
            } else {
                relationDao.insert(relationEntity);
            }
        }
    }


    /**
     * 根据属性分组id获取属性分组的关联的所有属性
     * @param attrgroupId 属性分组id
     * @return 指定属性分组id关联的所有属性的集合
     */
    @Override
    public List<AttrEntity> getRelationAttr(Long attrgroupId) {
        //1.根据传递的属性分组id , 获取(属性&属性分组)的关联关系
        List<AttrAttrgroupRelationEntity> entityList = relationDao.selectList(
                new QueryWrapper<AttrAttrgroupRelationEntity>()
                        .eq("attr_group_id", attrgroupId));
        //2.解析出关联关系中的属性id集合
        List<Long> attrIds = entityList.stream().map(AttrAttrgroupRelationEntity::getAttrId).collect(Collectors.toList());
        if (attrIds.size() == 0){
            return null;
        }
        //3.获取所有的属性集合
        return this.listByIds(attrIds);
    }


    /**
     * 根据属性分组ID查询当前属性分组没有关联的所有属性
     * @param params 前端传递的分页属性
     * @param attrgroupId 当前属性分组的id
     * @return 当前属性分组没有关联的所有属性的分页
     */
    @Override
    public PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId) {
        //1.当前属性分组只能关联自己所属分类里面的所有属性
        //2.当前属性分组只能关联当前绑定的分类中的别的属性分组没有引用的属性

        //1.获取当前属性分组的信息
        AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupId);
        //2.获取当前属性分组绑定的分类id
        Long catelogId = attrGroupEntity.getCatelogId();
        //3.获取当前分类下的所有属性分组
        List<AttrGroupEntity> group = attrGroupDao.selectList(
                new QueryWrapper<AttrGroupEntity>()
                .eq("catelog_id", catelogId));
        //4.抽取出当前分类下的所有属性分组的id
        List<Long> collect = group.stream()
                .map(AttrGroupEntity::getAttrGroupId)
                .collect(Collectors.toList());
        //5.获取所有属性分组关联的所有属性
        List<AttrAttrgroupRelationEntity> groupId = relationDao.selectList(
                new QueryWrapper<AttrAttrgroupRelationEntity>()
                        .in("attr_group_id", collect));
        //6.抽取所有的属性分组关联的属性id
        List<Long> attrIds = groupId.stream().map(AttrAttrgroupRelationEntity::getAttrId).collect(Collectors.toList());
        //7.获取所有关联属性中当前分类,和当前属性类型的属性
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>()
                .eq("catelog_id", catelogId)
                .eq("attr_type",ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());
        //8.排除所有已经有关联关系的属性
        if (attrIds.size()>0){
            wrapper.notIn("attr_id", attrIds);
        }
        //9.进行模糊查询
        String key = (String) params.get("key");
        if (StringUtils.isBlank(key)){
            wrapper.and((w)-> w.eq("attr_id",key).or().like("attr_name",key));
        }
        //10.进行查询 , 并进行分页
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), wrapper);
        return new PageUtils(page);
    }

    @Override
    public List<Long> selectSearchAttrs(List<Long> attrIds) {
        return baseMapper.selectSearchAttrIds(attrIds);
    }


}